import { _decorator, AudioClip, AudioSource, director, game, Node } from 'cc';
import { lodash } from './lodash';
import { ResLoader } from './ResLoader';
const { ccclass } = _decorator;

interface AudioData {
    source: AudioSource;
    isMusic: boolean;
}

interface AudioDataMap {
    [name: string]: AudioData;
}

@ccclass('AudioManager')
export class AudioManager {
    private _persistRootNode: Node = null!;
    static _instance: AudioManager;
    private _audioSources: AudioSource[] = [];

    musicVolume: number = 0.8;
    soundVolume: number = 1;
    audios: AudioDataMap = {};
    arrSound: AudioData[] = [];


    static get Instance() {
        if (this._instance) {
            return this._instance;
        }

        this._instance = new AudioManager();
        return this._instance;
    }

    init() {
        if (this._persistRootNode) return; //避免切换场景初始化报错
        this._persistRootNode = new Node('audio');
        director.getScene()!.addChild(this._persistRootNode);
        //@zh 标记为常驻节点，这样场景切换的时候就不会被销毁了
        director.addPersistRootNode(this._persistRootNode);
    }

    private _getAudioSource(clip: AudioClip) {
        let result: AudioSource | undefined;
        for (let i = 0; i < this._audioSources.length; ++i) {
            let audioSource = this._audioSources[i];
            if (!audioSource.playing) {
                result = audioSource;
                break;
            }
        }
        if (!result) {
            result = this._persistRootNode.addComponent(AudioSource);
            this._audioSources.push(result);
        }
        result.node.off(AudioSource.EventType.ENDED);
        result.clip = clip;
        result.currentTime = 0;
        return result;
    }


    /**
     * 播放音乐
     * @param {String} name 音乐名称可通过constants.AUDIO_MUSIC 获取
     * @param {Boolean} loop 是否循环播放
     */
    async playMusic(name: string, loop: boolean = true) {
        let path = 'music/' + name;

        if (this.audios[name]) {
            let audio = this.audios[name];
            if (audio.source.playing) {
            } else {
                audio.source.play();
            }
            return;
        }

        let clip = await ResLoader.loadAudio(path, 'Audio');
        let source = this._getAudioSource(clip);
        let tmp: AudioData = {
            source,
            isMusic: true,
        };
        this.audios[name] = tmp;
        source.volume = this.musicVolume;
        source.loop = loop;
        source.play();
    }

    /**
     * 播放音效
     * @param {String} name 音效名称可通过constants.AUDIO_SOUND 获取
     * @param {Boolean} loop 是否循环播放
     */
    async playSound(name: string, loop: boolean = false) {
        if (!this.soundVolume) {
            return;
        }

        //音效一般是多个的，不会只有一个
        let path = 'sound/' + name;

        let clip = await ResLoader.loadAudio(path, 'Audio');
        let source = this._getAudioSource(clip);
        let tmp: AudioData = {
            source,
            isMusic: false,
        };
        this.arrSound.push(tmp);

        if (loop) {
            this.audios[name] = tmp;
        }

        source.volume = this.soundVolume;
        source.loop = loop;
        source.play();

        source.node.on(AudioSource.EventType.ENDED, () => {
            lodash.remove(this.arrSound, (obj: AudioData) => {
                return obj.source === tmp.source;
            });
        });
    }

    stop(name: string) {
        if (this.audios.hasOwnProperty(name)) {
            let audio = this.audios[name];
            audio.source.stop();
        }
    }

    stopAll() {
        for (const i in this.audios) {
            if (this.audios.hasOwnProperty(i)) {
                let audio = this.audios[i];
                audio.source.stop();
            }
        }
    }

    stopAllMusic() {
        for (const i in this.audios) {
            if (this.audios.hasOwnProperty(i) && this.audios[i].isMusic) {
                let audio = this.audios[i];
                audio.source.stop();
            }
        }
    }

    getMusicVolume() {
        return this.musicVolume;
    }

    setMusicVolume(flag: number) {
        this.musicVolume = flag;
        for (let item in this.audios) {
            if (this.audios.hasOwnProperty(item) && this.audios[item].isMusic) {
                // this.changeState(item, flag);
                let audio = this.audios[item];
                audio.source.volume = this.musicVolume;
            }
        }
    }

    //看广告时先将音乐暂停
    pauseAll() {
        console.log("pause all music!!!");

        for (let item in this.audios) {
            if (this.audios.hasOwnProperty(item)) {
                let audio = this.audios[item];
                audio.source.pause();
            }
        }
    }

    resumeAll() {
        for (let item in this.audios) {
            if (this.audios.hasOwnProperty(item)) {
                let audio = this.audios[item];
                audio.source.play();
            }
        }
    }

    setSoundVolume(flag: number) {
        this.soundVolume = flag;
        for (let item in this.audios) {
            if (this.audios.hasOwnProperty(item) && !this.audios[item].isMusic) {
                // this.changeState(item, flag);
                let audio = this.audios[item];
                audio.source.volume = this.soundVolume;
            }
        }

        for (let idx = 0; idx < this.arrSound.length; idx++) {
            let audio = this.arrSound[idx];
            audio.source.volume = this.soundVolume;
        }
    }

    stopSingleSound(name: string) {
        if (this.audios.hasOwnProperty(name) && !this.audios[name].isMusic) {
            let audio = this.audios[name];
            audio.source.stop();
        }
    }
}


